package ec.linde.modulos.dao;

import java.util.List;
import java.util.Map;

import javax.ejb.Stateless;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Fetch;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import ec.linde.persistencia.entidades.proyectos.DetalleRegistroMaterial;
import ec.linde.persistencia.entidades.proyectos.RegistroMaterial;

/**
 * TODO: Agregar descripcion
 * 
 * @FechaCreacion: 29/09/2014
 * @author: Alex Carrillo
 * @FechaModificacion: 29/09/2014
 * @author: Alex Carrillo
 * @version: 1.0
 */
@Stateless
public class RegistroMaterialDao extends AbstractDao<RegistroMaterial> {
	/**
	 * Constructor por defecto que inicializa el AbstractDao con la clase ProdRegistroMaterialBodega
	 */
	public RegistroMaterialDao() {
		super(RegistroMaterial.class);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.asinfo.as2.dao.AbstractDaoAS2#obtenerListaPorPagina(int, int, java.lang.String, boolean, java.util.Map)
	 */
	public List<RegistroMaterial> obtenerListaPorPagina(int startIndex, int pageSize, String sortField, boolean sortOrder, Map<String, String> filters) {
		CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
		CriteriaQuery<RegistroMaterial> criteriaQuery = criteriaBuilder.createQuery(RegistroMaterial.class);
		Root<RegistroMaterial> from = criteriaQuery.from(RegistroMaterial.class);
		from.fetch("rdo", JoinType.LEFT).fetch("planOperativo", JoinType.LEFT).fetch("proyecto", JoinType.LEFT);

		final List<Expression<?>> expresiones = obtenerExpresiones(filters, criteriaBuilder, from);
		criteriaQuery.where(expresiones.toArray(new Predicate[expresiones.size()]));

		agregarOrdenamiento(sortField, sortOrder, criteriaBuilder, criteriaQuery, from);

		CriteriaQuery<RegistroMaterial> select = criteriaQuery.select(from);
		TypedQuery<RegistroMaterial> typedQuery = em.createQuery(select);
		agregarPaginacion(startIndex, pageSize, typedQuery);

		return typedQuery.getResultList();
	}

	/**
	 * 
	 * Retorna un lista para ser mostrado en un combo
	 * 
	 * @param sortField
	 * @param sortOrder
	 * @param filters
	 * @return
	 */
	public List<RegistroMaterial> obtenerListaCombo(String sortField, boolean sortOrder, Map<String, String> filters) {

		CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
		CriteriaQuery<RegistroMaterial> criteriaQuery = criteriaBuilder.createQuery(RegistroMaterial.class);
		Root<RegistroMaterial> from = criteriaQuery.from(RegistroMaterial.class);
		from.fetch("rdo", JoinType.LEFT).fetch("planOperativo", JoinType.LEFT);

		agregarOrdenamiento(sortField, sortOrder, criteriaBuilder, criteriaQuery, from);

		List<Expression<?>> empresiones = obtenerExpresiones(filters, criteriaBuilder, from);
		criteriaQuery.where(empresiones.toArray(new Predicate[empresiones.size()]));

		CriteriaQuery<RegistroMaterial> select = criteriaQuery.select(from);
		TypedQuery<RegistroMaterial> typedQuery = em.createQuery(select);

		return typedQuery.getResultList();
	}

	/**
	 * Carga ProdRegistroMaterialBodega
	 * 
	 * @param idRegistroMaterialBodega
	 * @return ProdRegistroMaterialBodega
	 */
	public RegistroMaterial cargarDetalle(int idRegistroMaterialBodega) {

		CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();

		CriteriaQuery<RegistroMaterial> cqCabecera = criteriaBuilder.createQuery(RegistroMaterial.class);
		Root<RegistroMaterial> fromCabecera = cqCabecera.from(RegistroMaterial.class);
		Fetch<Object, Object> rdo = fromCabecera.fetch("rdo", JoinType.LEFT);
		Fetch<Object, Object> planOperativo = rdo.fetch("planOperativo", JoinType.LEFT);
		Fetch<Object, Object> proyecto = planOperativo.fetch("proyecto", JoinType.LEFT);

		proyecto.fetch("usuario", JoinType.LEFT);
		proyecto.fetch("persona", JoinType.LEFT);
		proyecto.fetch("cliente", JoinType.LEFT);
		proyecto.fetch("sucursal", JoinType.LEFT);
		proyecto.fetch("contactoCliente", JoinType.LEFT);
		proyecto.fetch("contratista", JoinType.LEFT);
		proyecto.fetch("contactoContratista", JoinType.LEFT);

		Path<Integer> pathId = fromCabecera.get("idRegistroMaterial");
		cqCabecera.where(criteriaBuilder.equal(pathId, idRegistroMaterialBodega));
		CriteriaQuery<RegistroMaterial> selectRegistroMaterialBodega = cqCabecera.select(fromCabecera);
		RegistroMaterial registroMaterial = em.createQuery(selectRegistroMaterialBodega).getSingleResult();

		CriteriaQuery<DetalleRegistroMaterial> cqDetalleRegistroMaterialBodega = criteriaBuilder.createQuery(DetalleRegistroMaterial.class);
		Root<DetalleRegistroMaterial> fromDetalleRegistroMaterialBodega = cqDetalleRegistroMaterialBodega.from(DetalleRegistroMaterial.class);
		fromDetalleRegistroMaterialBodega.fetch("conceptoMaterial", JoinType.LEFT).fetch("prodMateriales", JoinType.LEFT);
		fromDetalleRegistroMaterialBodega.fetch("partida", JoinType.LEFT);
		cqDetalleRegistroMaterialBodega.where(criteriaBuilder.equal(fromDetalleRegistroMaterialBodega.join("registroMaterial"), registroMaterial));
		CriteriaQuery<DetalleRegistroMaterial> selectDetalleRegistroMaterial = cqDetalleRegistroMaterialBodega
				.select(fromDetalleRegistroMaterialBodega);

		List<DetalleRegistroMaterial> listaDetalleRegistroMaterial = em.createQuery(selectDetalleRegistroMaterial).getResultList();
		registroMaterial.setListaDetalleRegistroMaterial(listaDetalleRegistroMaterial);

		for (DetalleRegistroMaterial dpc : listaDetalleRegistroMaterial) {
			em.detach(dpc);
			dpc.setRegistroMaterial(registroMaterial);
		}

		return registroMaterial;
	}

}
